#-*-coding:utf8;-*-
from matplotlib.pyplot import savefig
from numpy import flatiter, left_shift, nan
from numpy.lib.function_base import append
from stockSelect10_soup_phone_1 import getstock
import pandas as pd
import time
import numpy as np
import mplfinance as mpf
import os
pd.options.mode.chained_assignment = None #avoid :pandas SettingWithCopyWarning

#通达信公式改写成python代码的最简实现方式: https://blog.csdn.net/u011218867/article/details/118242517,
# M:=55;
# N:=34;
# LC:=REF(CLOSE,1);
# RSI:=((SMA(MAX((CLOSE - LC),0),3,1) / SMA(ABS((CLOSE - LC)),3,1)) * 100);
# FF:=EMA(CLOSE,3);
# MA15:=EMA(CLOSE,21);
# DRAWTEXT(CROSS(85,RSI),75,'▼'),COLORGREEN;
# VAR1:=IF(YEAR>=2038 AND MONTH>=1,0,1);
# VAR2:=REF(LOW,1)*VAR1;
# VAR3:=SMA(ABS(LOW-VAR2),3,1)/SMA(MAX(LOW-VAR2,0),3,1)*100*VAR1;
# VAR4:=EMA(IF(CLOSE*1.3,VAR3*10,VAR3/10),3)*VAR1;
# VAR5:=LLV(LOW,30)*VAR1;
# VAR6:=HHV(VAR4,30)*VAR1;
# VAR7:=IF(MA(CLOSE,58),1,0)*VAR1;
# VAR8:=EMA(IF(LOW<=VAR5,(VAR4+VAR6*2)/2,0),3)/618*VAR7*VAR1;
# 吸筹:IF(VAR8>100,100,VAR8)*VAR1,COLORRED;
# 庄家吸筹:STICKLINE(吸筹>-150,0,吸筹,8,0),COLORRED;
# 散户: 100*(HHV(HIGH,M)-CLOSE)/(HHV(HIGH,M)-LLV(LOW,M)),COLORFFFF00,LINETHICK2;
# RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;
# K:=SMA(RSV,3,1);
# D:=SMA(K,3,1);
# J:=3*K-2*D;
# 庄家:EMA(J,6),COLORFF00FF,LINETHICK2;
# 第一买点:DRAWTEXT(CROSS(14,吸筹),10, '买1'),COLORYELLOW;
# 第二买点:DRAWTEXT(CROSS(庄家,散户) AND 庄家<50,30, '买2'),COLORRED;
# 第一卖点:DRAWTEXT(CROSS(88,庄家),80, '卖1'),COLORGREEN;
# 第二卖点:DRAWTEXT(CROSS(散户,庄家),60, '卖2'),COLORCYAN;

def ref(list_,window):
    #.shift函数功能：偏移
    return(pd.Series(list_).shift(window).to_list())
            
def ma(list_,window):
    return pd.Series(list_).rolling(window).mean().to_list()

def llv(list_,window):
    return pd.Series(list_).rolling(window).min().to_list()

def hhv(list_,window):
    return pd.Series(list_).rolling(window).max().to_list()

def ema(list_,N):
    """
    若Yn=EMA(Xn，N)，则Yn=[2*Xn+(N-1)*Yn-1]/(N+1)，其中Yn-1表示上一周期的Y值。
    """
    ema_=[]
    for i in range(len(list_)):
        if i==0:
            ema_.append(list_[0])    
        elif np.isnan(list_[i]) or np.isnan(ema_[-1]):
            ema_.append(list_[i])
        else:
            ema_.append(2*list_[i]/(N+1)+(N-1)/(N+1)*ema_[-1])
    return ema_

def sma(list_,N,M):
    """
    #
    SMA(X，N，M) X的N日累积平均，M为权重
    如Y=(XM+Y(N-M))/N
    """
    sma_=[]
    for i in range(len(list_)):
        #nan != nan,用np.isnan(x)来判断
        if i==0:
            sma_.append(list_[0])    
        elif np.isnan(list_[i]) or np.isnan(sma_[-1]):
            sma_.append(list_[i])
        else:
            sma_.append((M*list_[i]+(N-M)*sma_[-1])/N)
    return sma_

def add(list_,x):
    if isinstance(x,(float,int)):
        return [i+x for i in list_]
    elif type(x)==list and len(list_)==len(x):
        return [i+j for i,j in zip(list_,x)]

def subtraction(list_,x):
    if isinstance(x,(float,int)):
        return [i-x for i in list_]
    elif type(x)==list and len(list_)==len(x):
        return [i-j for i,j in zip(list_,x)]

def multiply(list_,x):
    if isinstance(x,(float,int)):
        return [i*x for i in list_]
    elif type(x)==list and len(list_)==len(x):
        return [i*j for i,j in zip(list_,x)]

def divide(list_,x):
    if isinstance(x,(float,int)):
        if x==0:
            raise ZeroDivisionError
        else:
            return [i/x for i in list_]
    elif type(x)==list and len(list_)==len(x):
        return [i/j if j!=0 else nan for i,j in zip(list_,x)]

def max_(list_,x):
    if isinstance(x,(float,int)):
        return [max(i,x) for i in list_]
    elif type(x)==list and len(list_)==len(x):
        return [max(i,j) for i,j in zip(list_,x)]   

def abs_(list_):
    return [abs(i) for i in list_]

def cross(x,list_):
    li=[]
    if isinstance(x,(float,int)):
        for i in range(len(list_)):
            if i<len(list_):#防止报list_1[i+1]超出索引
                li.append(x<=list_[i] and x>=list_[i+1])
            else:
                li.append(x==list_[-1])
        return li
    elif type(x)==list and len(list_)==len(x):
        for i in range(len(list_)):
            if i<len(list_)-1:#防止报list_1[i+1]超出索引
                li.append(x[i]<=list_[i] and x[i+1]>=list_[i+1])
            else: #此时i已为len(list_)
                li.append(x[i]==list_[i])
        return li

# from MyTT import *
# import talib

def xi_chou_check(file_name,code):
    #通达信公式改写成python代码的最简实现方式: https://blog.csdn.net/u011218867/article/details/118242517
    
    # def EMA(S,N):
    #     return pd.Series(S).ewm(span=N,adjust=False).mean().values
    gs=getstock(code)
    m=54
    n=34
    #用7天数据参与预测                        
    days=60
    df_ndays=gs.dayN(days)
    df_new=df_ndays[["open","high","low","close","hands"]]
    df_new.rename(columns={'hands': 'volume'},inplace=True)  
    # print(df_new) 
    #获得days天数据，由近到远
    # open_=df_ndays["open"].to_list() #.values和.to_list() 前者array,后者list
    close=df_ndays["close"].to_list()                  
    # high_=df_ndays["high"].to_list()
    low=df_ndays["low"].to_list()
    # print(add(close_,2))
    # lc=ref(close,1) #or gs.pre_close
    # df_lc=pd.DataFrame(lc)
    # df_lc.index=df_ndays.index
    # print(df_lc.to_string())

    #RSI:=(SMA(MAX((CLOSE - LC),0),3,1) / SMA(ABS(CLOSE - LC),3,1) * 100);
    # xx=subtraction(close,lc)
    # xxx=max_(subtraction(close,lc),0)
    # xxxx=sma(max_(subtraction(close,lc),0),3,1)

    # 测试MyTT和本地函数及Ta-lib返回结果是否相同
    # print(talib.get_functions())
    # print(ema(close,3)) #我的
    # print(EMA(close,3)) #MyTT
    # print(talib.EMA(np.array(close),timeperiod=3)) #talib的不一致，前几项不同，且前两项为nan，后面项趋于一致
    # print(sma(max_(subtraction(close,lc),0),3,1)) #我的
    # print(SMA(max_(subtraction(close,lc),0),3,1)) #MyTT，SMA一致
    # talib的SMA的计算方法是ma方法
    # print(hhv(high_,n)) #我的
    # print(HHV(high_,n)) #MyTT，HHV,LLV一致
    # print(ma(close,3))


    # rsi=multiply(divide(sma(max_(subtraction(close,lc),0),3,1),sma(abs_(subtraction(close,lc)),3,1)),100)
    # # FF:=EMA(CLOSE,3);
    # ff=ema(close,3)
    # # fff=list(EMA(close,3))
    # # print(subtraction(ff,fff)) 返回全零列表，表示 EMA和ema函数等价
    # # MA15:=EMA(CLOSE,15);
    # ma15=ema(close,15)
    # DRAWTEXT(CROSS(85,RSI),75,'▼'),COLORGREEN;
    #绘图函数：http://blog.sina.cn/dpool/blog/s/blog_163e3e3790102wzqr.html
    #cross(85,RSI)表示85水平线下穿RSI
    #在85下穿RSI处，在75位置画▼
    # VAR1:=IF(YEAR>=2038 AND MONTH>=1,0,1);
    #时间函数：http://www.360doc.cn/article/2581348_799358419.html
    Today=time.strftime("%Y-%m-%d-%H-%M-%S")
    year=int(Today.split('-')[0])
    month=int(Today.split('-')[1])
    var1=0 if year>=2038 and month>=1 else 1

    # VAR2:=REF(LOW,1)*VAR1;  
    var2=multiply(ref(low,1),var1)

    # VAR3:=SMA(ABS(LOW-VAR2),3,1)/SMA(MAX(LOW-VAR2,0),3,1)*100*VAR1;
    var3=multiply(divide(sma(abs_(subtraction(low,var2)),3,1),sma(max_(subtraction(low,var2),0),3,1)),100*var1)
    # df_var3=pd.DataFrame(var3)
    # df_var3.index=df_ndays.index
    # print(df_var3.to_string()) #the same with tdx

    # VAR4:=EMA(IF(CLOSE*1.3,VAR3*10,VAR3/10),3)*VAR1;
    var4=multiply(ema([var3[i]*10 if close[i]*1.3 else var3[i]/10 for i in range(len(close))] ,3),var1)
    # df_var4=pd.DataFrame(var4)
    # df_var4.index=df_ndays.index
    # print(df_var4.to_string()) #the same with tdx

    # VAR5:=LLV(LOW,30)*VAR1;
    var5=multiply(llv(low,30),var1)
    # df_var5=pd.DataFrame(var5)
    # df_var5.index=df_ndays.index
    # print(df_var5.to_string()) #the same with tdx
    # VAR6:=HHV(VAR4,30)*VAR1;
    var6=multiply(hhv(var4,30),var1)
    # df_var6=pd.DataFrame(var6)
    # df_var6.index=df_ndays.index
    # print(df_var6.to_string()) #the same with tdx

    #通达信金融终端程序下载地址， 下载地址 https://www.tdx.com.cn/soft.html
    # VAR7:=IF(MA(CLOSE,58),1,0)*VAR1;
    var7=multiply([1 if i else 0 for i in ma(close,58)],var1)
    # df_var7=pd.DataFrame(var7)
    # df_var7.index=df_ndays.index
    # print(df_var7.to_string())#the same with tdx

    # VAR8:=EMA(IF(LOW<=VAR5,(VAR4+VAR6*2)/2,0),3)/618*VAR7*VAR1;
    var8=multiply(ema([(var4[index]+var6[index]*2)/2 if i<=j else 0 for index,(i,j)  in enumerate(zip(low,var5))],3),multiply(divide(var7,618),var1))
    output_File = open(file_name,'a+') #a+: 附加读写方式打开
    # print(var8)
    if len(var8)>0:
        output_File.write('{},{}\n'.format(str(code).zfill(6),str(round(var8[-1],2))))
        output_File.flush()#每次写入都保存一次，防止中断全部丢失
    else:
        output_File.flush()
    return "%s complete"%str(code).zfill(6)

    # df_var8=pd.DataFrame(var8)
    # df_var8.index=df_ndays.index
    # print(df_var8.to_string())#the same with tdx

    # 吸筹:IF(VAR8>100,100,VAR8)*VAR1,COLORRED;
    # xi_chou=multiply([100 if i>100 else i for i in var8],var1)
    # df_xi_chou=pd.DataFrame(xi_chou)
    # df_xi_chou.index=df_ndays.index
    # # print(df_xi_chou.to_string())#
    # # 庄家吸筹:STICKLINE(吸筹>-150,0,吸筹,8,0),COLORRED;
    # #STICKLINE(COND，PRICE1，PRICE2，WIDTH，EMPTY) 当COND条件满足时，在PRICE1和PRICE2位置之间画柱状线，宽度为WIDTH(10为标准间距)，EMPTH不为0则画空心柱。
    # #在吸筹>-150时，画高度为吸筹，宽度为8的实心柱，颜色红色
    # zhuang_jia_xi_chou=[i if i>-150 else 0 for i in xi_chou]
    # df_zhuang_jia_xi_chou=pd.DataFrame(zhuang_jia_xi_chou)
    # df_zhuang_jia_xi_chou.index=df_ndays.index
    # # print(df_zhuang_jia_xi_chou.to_string())
    
    # # 散户: 100*(HHV(HIGH,M)-CLOSE)/(HHV(HIGH,M)-LLV(LOW,M)),COLORFFFF00,LINETHICK2;
    # san_hu=divide(multiply(subtraction(hhv(high_,m),close),100),subtraction(hhv(high_,m),llv(low,m)))
    # df_san_hu=pd.DataFrame(san_hu)
    # df_san_hu.index=df_ndays.index
    # # print(df_san_hu.to_string())#the same with tdx

    # # RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;
    # rsv=multiply(divide(subtraction(close,llv(low,n)),subtraction(hhv(high_,n),llv(low,n))),100)
    # # K:=SMA(RSV,3,1);
    # k=sma(rsv,3,1)
    # # D:=SMA(K,3,1);
    # d=sma(k,3,1)
    # # J:=3*K-2*D;
    # j=subtraction(multiply(k,3),multiply(d,2))
    ##庄家:EMA(J,6),COLORFF00FF,LINETHICK2;
    # zhuang_jia=ema(j,6)
    # df_zhuang_jia=pd.DataFrame(zhuang_jia)
    # df_zhuang_jia.index=df_ndays.index
    # print(df_zhuang_jia.to_string())#the same with tdx

    # # 第一买点:DRAWTEXT(CROSS(14,吸筹),10, '买1'),COLORYELLOW;
    # first_buy_point=cross(14,xi_chou)
    # # print(first_buy_point)
    # # print(CROSS(np.full(len(xi_chou),14),np.array(xi_chou)))
    # # 第二买点:DRAWTEXT(CROSS(庄家,散户) AND 庄家<50,30, '买2'),COLORRED;
    # second_buy_point=cross(zhuang_jia,san_hu)
    # # print(np.array(second_buy_point))
    # # print(CROSS(np.array(zhuang_jia),np.array(san_hu))) #不同
    # # 第一卖点:DRAWTEXT(CROSS(88,庄家),80, '卖1'),COLORGREEN;
    # first_sell_point=cross(88,zhuang_jia)
    # # print(first_sell_point)
    # # 第二卖点:DRAWTEXT(CROSS(散户,庄家),60, '卖2'),COLORCYAN;
    # second_sell_point=cross(san_hu,zhuang_jia)
    # # print(second_sell_point)

def draw(df_new,var4,var5,var6,var7,var8):
    #画图
    add_plot = [
        #画var4
        mpf.make_addplot(var4,color='r'),
        #画var5
        mpf.make_addplot(var5,color='g'),
        #画var6
        mpf.make_addplot(var6,color='y'),
        #画var7
        mpf.make_addplot(var7,color='b'),
        #画var8
        mpf.make_addplot(var8,color='w'),
    ]
    my_color = mpf.make_marketcolors(up='red',down='cyan',volume='blue',inherit=True)
    my_style = mpf.make_mpf_style(
        facecolor = 'black',
        marketcolors = my_color,
        gridaxis='horizontal',
        gridcolor='red',
        gridstyle='--',
        y_on_right=False
    )
    mpf.plot(df_new,
            addplot=add_plot,
            type='candle',
            style=my_style,
            figratio=(5,3),
            figscale=2,
            volume=True,
            savefig='600691.png'
    )

#用threading模块
def multi_thread_xi_chou_thread(file_name,code_list):
    # 使用for循环执行100个线程，并使用阻塞join
    import time
    import threading

    start = time.perf_counter()

    threads=[]
    j=0
    for i in code_list:
        t = threading.Thread(target=xi_chou_check,args=(file_name,i))
        t.start()
        print("thread%s is started"%i)
        threads.append(t)

    for thread in threads:
        thread.join()
        print("thread%s is joined"%thread)

    finish = time.perf_counter()
    print(f"Finished in {round(finish-start,2)} second(s)")
    
def multi_thread_xi_chou_check(file_name,code_list):
    """
    使用线程池，由系统自动分配线程数量，并打印线程目标函数的返回结果
    """  
    #在append之前先删除原数据表
    import concurrent.futures
    with concurrent.futures.ThreadPoolExecutor() as executor:     
        # results=executor.map(f10_into_df,code_index_list)
        results=[ executor.submit(xi_chou_check,file_name,i) for i in code_list]
        # for result in results:#<Future at 0x1669cf023a0 state=pending>
        #     print(result)
        for f in concurrent.futures.as_completed(results):
            print(f.result())      

def send_to_email(subject_str,filepath_str): #filepath_str:'C:\1.txt'
    import yagmail

    # 登录你的邮箱
    yag = yagmail.SMTP(user = 'jamal121@163.com', password = 'kirin107105', host = 'smtp.163.com')
    # 发送邮件
    yag.send(to = ['jamal121@163.com'], subject = subject_str, contents = ['内容',filepath_str])
        
if __name__=='__main__':
    path=os.getcwd()
    # df=pd.read_csv(path+'/xi_chou.csv')
    df=pd.read_csv(path+'/Result/after_process.csv')
    df1=df[["code",'f10']]
    df1.query('f10==True',inplace=True)
    df1.drop(columns=['f10'],inplace=True)
    df1.to_csv("f10_true.csv")
    code_index_list=df1['code'].to_list()
        # file_name="{}.csv".format("xi_chou_"+str(time.strftime("%Y_%m_%d_%H_%M_%S")))
    file_name="{}.csv".format("xi_chou_"+str(time.strftime("%Y_%m_%d_%H")))
    if os.path.exists(file_name): os.remove(file_name)  #because  open(file_name,'a+') #a+: 附加读写方式打开 
    multi_thread_xi_chou_check(file_name,code_index_list)
    # multi_thread_xi_chou_thread(file_name,code_index_list)
    # df_output=pd.DataFrame(file_name)
    # df_output.to_csv(file_name) #已经file.flush()
    #结果发送邮件
    # send_to_email(file_name,path+'/'+file_name)